home *** CD-ROM | disk | FTP | other *** search
- /* ScheduleMatches ----------------------------------------
- *
- * In response to Nov 93 MacTech programmer's challenge.
- *
- * Object is to:
- * 1) form all combinations of 'numTeams' 'teamNames',
- * taken two at a time (numTeams even);
- * 2) match these pairs to 'numTeams'/2
- * 'playingAreaNames';
- * 3) schedule 'numTeams'/2 "matches" at a time, starting
- * at 12 noon, with a new set of such matches
- * scheduled every 15 minutes, until all combinations
- * are used;
- * 4) write the whole schedule out to a given ANSI file
- * stream.
- *
- * Some observations:
- *
- * number of combinations = C(numTeams,2) =
- * numTeams*(numTeams-1)/2.
- * There are then (numTeams-1) sets of matches, or,
- * times, which must be scheduled.
- *
- * The pairs can be generated geometrically using
- * central cyclical pattern as demonstrated for
- * numTeams = 6:
- *
- * 1 Connecting rods have fixed
- * | orientation. 0 stays in center.
- * | Other digits cycle clockwise,
- * 2---\ 0 /---5 or, cc, around circumference.
- * ---
- *
- * 3-----4
- *
- * Suggested formatting is as follows:
- *
- * 12:xx
- * areaU: nameJ vs nameK
- * areaV: nameL vs nameM
- * .
- * .
- * {blank line}
- * 12:xx
- * .
- * .
- *
- * billKarsh - solution author.
- *
- */
-
- #pragma options( honor_register, !assign_registers )
- #pragma options( !check_ptrs )
-
- #include <string.h>
- #include <stdio.h>
-
- void ScheduleMatches(
- unsigned short numTeams,
- Str255 teamNames[],
- Str255 playingAreaNames[],
- FILE *outputfile );
-
- #define BufSize 1024
-
- // BufIt modifier codes
- #define kTime -1 // write time
- #define kStrn 1 // write string + '\n'
- #define kStrSep 2 // write string + ': '
- #define kStrVs 4 // write string + ' vs '
-
- // useful shorthand inside BufIt
- // make sure n bytes available in buffer,
- // else empty it out
-
- #define BufReady( n ) \
- if( n > b->avail ) { \
- b->p = p; \
- BufFlush(); \
- p = b->buf; \
- }
-
- typedef struct {
- FILE *file; // ANSI stream
- Byte *buf; // start of private buffer
- Byte *p; // current position in buffer
- short avail; // available bytes in buffer
- short padding;// global data 4-byte aligned
- } BufRec;
-
- static BufRec gBuf;
-
-
- /* BufFlush -----------------------------------------------
- *
- * Write current buffer to file.
- */
-
- static void BufFlush( void )
- {
- register BufRec *b = &gBuf;
- size_t n = b->p - b->buf;
-
- if( n ) {
-
- fwrite( b->buf, 1, n, b->file );
-
- // reset buffer
-
- b->p = b->buf;
- b->avail = BufSize;
- }
- }
-
-
- /* BufIt --------------------------------------------------
- *
- * 1) Write string to local buffer if room,
- * otherwise,
- * 2) Dump buffer to file,
- * 3) resume with step 1.
- *
- * If behavior code, mod, as defined above is >= 0:
- * data is data starting address,
- * nBytes of data to write.
- *
- * If mod is special code kTime:
- * data indexes internal minute string,
- * nBytes = hour.
- */
-
- static void BufIt(
- register Byte *data,
- register short nBytes,
- short mod )
- {
- register BufRec *b = &gBuf;
- register Byte *p = b->p;
- static Byte mins[8] = "00153045";
-
- if( mod < 0 ) { // write a time
-
- BufReady( 7 );
-
- *p++ = '\n';
-
- // hour
-
- if( !nBytes ) {
- *p++ = '1';
- *p++ = '2';
- b->avail--;
- }
- else
- *p++ = nBytes + '0';
-
- *p++ =':';
-
- // mins
-
- data += (long)mins;
- *p++ = *data++;
- *p++ = *data;
-
- *p++ = '\n';
- b->avail -= 6;
- }
- else { // write a string
-
- BufReady( nBytes + mod );
-
- memcpy( p, data, nBytes );
- p += nBytes;
- b->avail -= nBytes + mod;
-
- switch( mod ) { // write string suffix
- case kStrn:
- *p++ = '\n';
- break;
- case kStrSep:
- *p++ = ':';
- *p++ = ' ';
- break;
- case kStrVs:
- *p++ = ' ';
- *p++ = 'v';
- *p++ = 's';
- *p++ = ' ';
- break;
- }
- }
-
- b->p = p;
- }
-
-
- /* ScheduleMatches ----------------------------------------
- *
- * Driver routine.
- */
-
- void ScheduleMatches(
- unsigned short numTeams,
- Str255 teamNames[],
- Str255 playingAreaNames[],
- FILE *outputfile )
- {
- register Byte *area, *tmJ, *tmK;
- register short N = numTeams,
- set = 0, nAreas;
- register long t1 = (long)*teamNames + 256,
- tN = t1 + ((N-2)<<8);
- Byte localBuf[BufSize];
-
- if( !N || N & 1 ) return;
-
- // init local buffer
-
- gBuf.file = outputfile;
- gBuf.buf = gBuf.p = localBuf;
- gBuf.avail = BufSize;
-
- // loop over sets of matches (times)
-
- do {
-
- // do first pair separately, because team[0]
- // is at center, so this pair disjoint from
- // others.
-
- nAreas = N>>1;
- area = *playingAreaNames;
-
- BufIt( (Byte*)((set&3)<<1), set>>2, kTime );
- BufIt( area+1, *area, kStrSep );
-
- tmJ = (Byte*)t1 - 256;
- tmK = (Byte*)t1 + (set<<8);
-
- BufIt( tmJ+1, *tmJ, kStrVs );
- BufIt( tmK+1, *tmK, kStrn );
-
- tmJ = tmK;
-
- // loop over remaining areas (pairs)
-
- while( --nAreas ) {
-
- area += 256;
- BufIt( area+1, *area, kStrSep );
-
- // next pair
-
- tmJ = (long)tmJ < tN ? tmJ+256 : (Byte*)t1;
- tmK = (long)tmK > t1 ? tmK-256 : (Byte*)tN;
-
- BufIt( tmJ+1, *tmJ, kStrVs );
- BufIt( tmK+1, *tmK, kStrn );
- };
-
- } while( ++set < N - 1 );
-
- BufFlush();
- }
-